package main

import (
	"bufio"
	"encoding/json"
	"flag"
	"fmt"
	"github.com/Knetic/govaluate"
	"io"
	"io/ioutil"
	"log"
	"math/rand"
	"os"
	"strconv"
	"sync"
	"time"
)

func readTerminal() {
	var buf [16]byte
	os.Stdin.Read(buf[:])
	os.Stdin.WriteString(string(buf[:]))
}

func readFile() {
	file, err := os.Open("./data.txt")
	if err != nil {
		fmt.Println("open file failed!,err:", err)
		return
	}
	defer file.Close()

	var buf [10]byte
	var content []byte
	for {
		n, err := file.Read(buf[:])
		if err == io.EOF {
			break
		}
		if err != nil {
			fmt.Println("read file err", err)
			return
		}
		content = append(content, buf[:n]...)
	}
	fmt.Println(string(content))
}

func createFile() {
	file, err := os.Create("./data.txt")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer file.Close()
	for i := 0; i < 5; i++ {
		file.WriteString("I am yzp\n")
		file.Write([]byte("hello world\n"))
	}
}

func copyFile() {
	srcFile, err := os.Open("./data.txt")
	if err != nil {
		fmt.Println(err)
		return
	}
	dstFile, err2 := os.Create("./dataCopy.txt")
	if err2 != nil {
		fmt.Println(err2)
		return
	}
	buf := make([]byte, 1024)
	for true {
		n, err := srcFile.Read(buf)
		if err == io.EOF {
			fmt.Println("读取完毕")
			return
		}
		if err != nil {
			fmt.Println(err)
			break
		}
		dstFile.Write(buf[:n])
	}
	defer srcFile.Close()
	defer dstFile.Close()
}

func wr() {
	file, err := os.OpenFile("./data1.txt", os.O_CREATE|os.O_WRONLY, 0666)
	if err != nil {
		return
	}
	defer file.Close()
	writer := bufio.NewWriter(file)
	for i := 0; i < 3; i++ {
		writer.WriteString("hello \n")
	}
	writer.Flush()
}

func re() {
	file, err := os.Open("./data1.txt")
	if err != nil {
		return
	}
	defer file.Close()
	reader := bufio.NewReader(file)
	for true {
		line, isPrefix, err := reader.ReadLine()
		if err == io.EOF {
			break
		}
		if err != nil {
			return
		}
		fmt.Println(isPrefix, string(line))
	}
}

func wr2() {
	err := ioutil.WriteFile("data1.txt", []byte("www.baidu.com"), 0666)
	if err != nil {
		fmt.Println(err)
		return
	}
}

func re2() {
	file, err := ioutil.ReadFile("./data1.txt")
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(string(file))
}

func catt(r *bufio.Reader) {
	for true {
		buf, err := r.ReadBytes('\n')
		if err == io.EOF {
			break
		}
		fmt.Fprintf(os.Stdout, "%s", buf)
	}
}

func doCar() {
	flag.Parse()
	if flag.NArg() == 0 {
		catt(bufio.NewReader(os.Stdin))
	}
	for i := 0; i < flag.NArg(); i++ {
		file, err := os.Open(flag.Arg(i))
		if err != nil {
			fmt.Fprintf(os.Stdout, "read from %s failed,err:%v\n", flag.Arg(i), err)
			continue
		}
		catt(bufio.NewReader(file))
		fmt.Fprintf(os.Stdout, "=======>>>>>>>>\n")
	}
}

func test(x, y int, s string) (int, string) {
	n := x + y
	return n, fmt.Sprintf(s, n)
}

func test2(fn func() int) int {
	return fn()
}

type FormatFunc func(s string, x, y int) string

func format(fn FormatFunc, s string, x, y int) string {
	return fn(s, x, y)
}

func doFormat() {
	s1 := test2(func() int {
		return 100
	})
	println(s1)
	s2 := format(func(s string, x, y int) string {
		return fmt.Sprintf(s, x, y)
	}, "%d,%d", 10, 20)
	fmt.Println(s2)
}

func test3(s string, args ...int) string {
	var x int
	for _, i := range args {
		x += i
	}
	return fmt.Sprintf(s, x)
}

func doTest3() {
	fmt.Println(test3("sum:%d", []int{1, 2, 3, 4}...))
}

type Manager struct {
	User2
	title string
}

type User2 struct {
	Id   int
	Name string
	Age  int
}

func (u *User2) ToString() string {
	return fmt.Sprintf("User:%p, %v", u, u)
}

func (u *Manager) ToString() string {
	return fmt.Sprintf("Manager: %p, %v", u, u)
}

func doToString() {
	m := Manager{User2{1, "Tom", 12}, "Administrator"}

	fmt.Println(m.ToString())

	fmt.Println(m.User2.ToString())
}

type User3 struct {
	id   int
	name string
}

func (u User3) Test() {
	fmt.Printf("%p,%v\n", u, u)
}

func doUser3() {
	u := User3{1, "Tom"}
	u.Test()
	mValue := u.Test
	mValue()
	mExpress := (*User3).Test
	mExpress(&u)
}

func timer() {
	timer1 := time.NewTimer(time.Second * 2)
	t1 := time.Now()
	fmt.Printf("t1:%v\n", t1)
	t2 := <-timer1.C
	fmt.Printf("t2:%v\n", t2)
}

func timer2() {
	newTimer := time.NewTimer(time.Second)
	<-newTimer.C
	fmt.Println("时间到")
}

func timer3() {

	<-time.After(time.Second)
}

func test1() {
	ch := make(chan int, 1)
	go test4(ch)
	time.Sleep(time.Second)
	ch <- 10
	fmt.Println("发送成功")
}

func test4(ch chan int) {
	ret := <-ch
	fmt.Println("接收成功", ret)
}

func test5() {
	ch := make(chan int)
	go func() {
		for i := 0; i < 5; i++ {
			ch <- i
		}
		close(ch)
	}()
	for true {
		if data, ok := <-ch; ok {
			fmt.Println(data)
		} else {
			break
		}
	}
	fmt.Println("main() over")
}

func test6() {
	ch1 := make(chan int)
	ch2 := make(chan int)
	go func() {
		for i := 0; i < 10; i++ {
			ch1 <- i
		}
		close(ch1)
	}()
	go func() {
		for true {
			i, ok := <-ch1
			if !ok {
				break
			}
			ch2 <- i * i
		}
		close(ch2)
	}()
	for i := range ch2 {
		fmt.Println(i)
	}
}

func counter(out chan<- int) {
	for i := 0; i < 10; i++ {
		out <- i
	}
	close(out)
}
func square(out chan<- int, in <-chan int) {
	for i := range in {
		out <- i * i
	}
	close(out)
}
func printer(in <-chan int) {
	for i := range in {
		fmt.Println(i)
	}
}

func test7() {
	ch1 := make(chan int)
	ch2 := make(chan int)
	go counter(ch1)
	go square(ch2, ch1)
	printer(ch2)
}

type Job struct {
	Id      int
	RandNum int
}

type Result struct {
	job *Job
	sum int
}

func test8() {
	jobChan := make(chan *Job, 128)
	resultChan := make(chan *Result, 128)
	createPool(64, jobChan, resultChan)
	go func(resultChan chan *Result) {
		for result := range resultChan {
			fmt.Printf("job id %v,randnum:%v,result %d\n", result.job.Id, result.job.RandNum, result.sum)
		}
	}(resultChan)
	var id int
	for true {
		id++
		randNum := rand.Int()
		job := &Job{Id: id, RandNum: randNum}
		jobChan <- job
	}
}

func createPool(num int, jobChan chan *Job, resultChan chan *Result) {
	for i := 0; i < num; i++ {
		go func(jobChan chan *Job, resultChan chan *Result) {
			for job := range jobChan {
				randNum := job.RandNum
				var sum int
				for randNum != 0 {
					sum += randNum % 10
					randNum /= 10
				}
				r := &Result{
					job: job,
					sum: sum,
				}
				resultChan <- r
			}
		}(jobChan, resultChan)
	}
}

func test9(ch chan string) {
	time.Sleep(time.Second)
	ch <- "test1"
}
func test10(ch chan string) {
	time.Sleep(time.Second)
	ch <- "test2"
}
func doTest11() {
	ch1 := make(chan string, 1)
	ch2 := make(chan string, 1)
	go test9(ch1)
	go test10(ch2)
	select {
	case s1 := <-ch1:
		fmt.Println("s1=", s1)
	case s2 := <-ch2:
		fmt.Println("s2=", s2)
	}
}

func write(ch chan string) {
	for true {
		select {
		case ch <- "hello":
			fmt.Println("write hello")
		default:
			fmt.Println("channel full")
		}
		time.Sleep(time.Millisecond * 100)
	}
}

func test12() {
	ch := make(chan string, 10)
	go write(ch)
	for s := range ch {
		fmt.Println("res:", s)
		time.Sleep(time.Second)
	}
}

var x1 int64
var wg1 sync.WaitGroup
var lock sync.Mutex
var rwlock sync.RWMutex

func add() {
	for i := 0; i < 5000; i++ {
		lock.Lock()
		x1++
		lock.Unlock()
	}
	wg1.Done()
}
func test13() {
	wg1.Add(2)
	go add()
	go add()
	wg1.Wait()
	fmt.Println(x1)
}

func write2() {
	rwlock.Lock()
	x1++
	time.Sleep(10 * time.Millisecond)
	rwlock.Unlock()
	wg1.Done()
}

func read() {
	rwlock.RLock()
	time.Sleep(time.Millisecond)
	rwlock.RUnlock()
	wg1.Done()
}

func testRWLock() {
	start := time.Now()
	for i := 0; i < 10; i++ {
		wg1.Add(1)
		go write2()
	}
	for i := 0; i < 1000; i++ {
		wg1.Add(1)
		go read()
	}
	wg1.Wait()
	end := time.Now()
	fmt.Println(end.Sub(start))
}

var mm = make(map[string]int)

func get(key string) int {
	return mm[key]
}

func set(key string, value int) {
	mm[key] = value
}

func test14() {
	wg := sync.WaitGroup{}
	for i := 0; i < 20; i++ {
		wg.Add(1)
		go func(n int) {
			key := strconv.Itoa(n)
			set(key, n)
			fmt.Printf("k=%v,v=%v\n", key, get(key))
			wg.Done()
		}(i)
	}
	wg.Wait()
}

var mm2 = sync.Map{}

func test15() {
	wg := sync.WaitGroup{}
	for i := 0; i < 20; i++ {
		wg.Add(1)
		go func(n int) {
			key := strconv.Itoa(n)
			mm2.Store(key, n)
			value, _ := mm2.Load(key)
			fmt.Printf("k=%v,v=%v\n", key, value)
			wg.Done()
		}(i)
	}
	wg.Wait()
}

func doArgs2() {
	var name string
	var age int
	var married bool
	var delay time.Duration
	flag.StringVar(&name, "name", "张三", "姓名")
	flag.IntVar(&age, "age", 18, "age")
	flag.BoolVar(&married, "married", false, "婚否")
	flag.DurationVar(&delay, "d", 0, "延迟时间间隔")

	flag.Parse()
	fmt.Println(name, age, married, delay)
	fmt.Println(flag.Args())
	fmt.Println(flag.NArg())
	fmt.Println(flag.NFlag())
}

func doLog() {
	log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
	log.Println("普通日志")
	v := "很普通的"
	log.SetPrefix("[pprof]")
	log.Printf("这是一条%s日志\n", v)
	log.Fatalln("触发 fatal 的日志")
	log.Panicln("触发 panic 的日志")
}

func doLog2() {
	file, err := os.OpenFile("./logger.log", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		fmt.Println("open file failed,err:", err)
		return
	}
	log.SetOutput(file)
	log.SetPrefix("[pprof]")
	log.Fatalln("触发 fatal 的日志")
	log.Panicln("触发 panic 的日志")
}

func doLog3() {
	log := log.New(os.Stdout, "<New>", log.Lshortfile|log.Ldate|log.Ltime)
	log.Println("普通日志")
}

func doRange() {

	a := [3]int{1, 2, 3}
	for i, v := range a {
		if i == 0 { // 在修改前，我们先修改原数组。
			a[1], a[2] = 999, 999
			fmt.Println(a) // 确认修改有效，输出 [0, 999, 999]。
			fmt.Println(a)
		}
		a[i] = v + 100
	}
	fmt.Println(a)

	//s := "abcd"
	//for _, i := range s {
	//	println(i)
	//}
}

type Person struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
}

func doJson() {

	names := []string{"Alice", "Bob"}
	data, err2 := json.Marshal(names)
	if err2 != nil {
		log.Fatal(err2)
	}
	fmt.Println(string(data))

	person := Person{Name: "yzp", Age: 23}
	bytes, err := json.Marshal(person)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(string(bytes))
	err2 = json.Unmarshal(bytes, &person)
	if err2 != nil {
		log.Fatal(err2)
	}
	fmt.Println(person.Age, person.Name)
}

type Data struct {
	Name    string      `json:"name"`
	Payload interface{} `json:"payload"`
}

func doJson2() {
	jsonStr := `{"name":"Event","payload":{"type":"message","content":"Hello, world!"}}`
	var data Data
	err := json.Unmarshal([]byte(jsonStr), &data)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(data.Name)
	payload, ok := data.Payload.(map[string]interface{})
	if ok {
		fmt.Println(payload["type"])
		fmt.Println(payload["content"])
	}

}

func demo1() {
	expr, err := govaluate.NewEvaluableExpression("10 > 0")
	if err != nil {
		log.Fatal("syntax error:", err)
	}

	result, err := expr.Evaluate(nil)
	if err != nil {
		log.Fatal("evaluate error:", err)
	}

	fmt.Println(result)
}
func main() {
	demo1()
}
